package cn.chenfeifx.core.controls;

import cn.chenfeifx.core.common.FxUtil;
import cn.chenfeifx.core.common.ResourcesLoader;
import cn.chenfeifx.core.common.SimpleControl;
import javafx.animation.FadeTransition;
import javafx.animation.Interpolator;
import javafx.animation.ParallelTransition;
import javafx.animation.TranslateTransition;
import javafx.beans.property.*;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.util.Duration;
import org.kordamp.ikonli.antdesignicons.AntDesignIconsOutlined;
import org.kordamp.ikonli.javafx.FontIcon;

/**
 * 抽屉
 */
public final class CFDrawer {

    private final DoubleProperty size = new SimpleDoubleProperty();
    private final StringProperty title = new SimpleStringProperty("标题");
    private final ObjectProperty<Node> center = new SimpleObjectProperty<>();
    private final ObjectProperty<Node> bottom = new SimpleObjectProperty<>();
    private final StackPane parent;
    private Position position = Position.RIGHT;
    private final DrawerNode drawerNode;

    /**
     * 提供一个StackPane作为父组件，会将抽屉添加到父组件，在调用show()方法进行展示
     *
     * @param size：Position位置不同 size表示的参数不同：TOP（size=height）, RIGHT（size=width）, BOTTOM（size=height）, LEFT（size=width）
     * @param parent
     */
    public CFDrawer(double size, StackPane parent) {
        this.size.set(size);
        this.parent = parent;
        drawerNode = new DrawerNode();
    }

    public CFDrawer(double size, StackPane parent, Node center) {
        this.size.set(size);
        this.parent = parent;
        drawerNode = new DrawerNode();
        this.center.set(center);
    }

    public void show() {
        drawerNode.show();
    }

    public void show(Position position) {
        drawerNode.show(position);
    }

    public void setCenter(Node center) {
        this.center.set(center);
    }

    public void setBottom(Node bottom) {
        this.bottom.set(bottom);
    }

    public void setTitle(String title) {
        this.title.set(title);
    }

    /**
     * 抽屉组件
     */
    private class DrawerNode extends StackPane {
        //基本属性
        private static final String STYLE_SHEET = ResourcesLoader.load("/cn/chenfeifx/core/css/cf-drawer.css");

        //UI布局
        private final StackPane modal = new StackPane(); // 遮罩层
        //
        private final Label titleLabel = SimpleControl.getLabel("", SimpleControl.LabelEnum.H4);
        private final Button close = new Button();
        private final StackPane header = new StackPane(titleLabel, close); // 头部
        private final StackPane content = new StackPane(); // 内容区域
        private final BorderPane main = new BorderPane();

        public DrawerNode() {
            initialize();
        }

        private void initialize() {
            main.setTop(header);
            getChildren().addAll(this.modal, this.main);
            FxUtil.clipRect(this); // 裁剪使抽屉移动时不会超出父组件
            // 主要区域
            header.setMaxSize(USE_COMPUTED_SIZE, USE_PREF_SIZE);
            StackPane.setAlignment(titleLabel, Pos.CENTER_LEFT);
            StackPane.setAlignment(close, Pos.CENTER_RIGHT);
            close.setGraphic(new FontIcon(AntDesignIconsOutlined.CLOSE));
            VBox.setVgrow(content, Priority.ALWAYS);
            titleLabel.textProperty().bind(title);
            //遮罩层
            modal.setBackground(new Background(new BackgroundFill(Color.rgb(0, 0, 0, 0.3), null, null)));
            modal.setOpacity(0);
            //点击遮罩层关闭
            modal.setOnMouseClicked(event -> hide());
            close.setOnMouseClicked(event -> hide());
            //styleClass
            main.getStyleClass().add("main");
            close.getStyleClass().add("close");
            //
            main.centerProperty().bind(center);
            main.bottomProperty().bind(bottom);
        }

        // 动画属性
        private final TranslateTransition TT = new TranslateTransition(Duration.millis(300), this.main);
        private final FadeTransition FT = new FadeTransition(Duration.millis(300), this.modal);
        private final ParallelTransition PT = new ParallelTransition(TT, FT);

        /**
         * 从右侧展示抽屉
         */
        public void show() {
            show(Position.RIGHT);
        }

        /**
         * 指定方向展示抽屉
         *
         * @param pos
         */
        public void show(Position pos) {
            position = pos;
            setShowInfo();
            parent.getChildren().add(this);// 添加抽屉
            FT.setFromValue(0);
            FT.setToValue(1);
            PT.setInterpolator(Interpolator.LINEAR);
            PT.play();
            PT.setOnFinished((event) -> {
            });
        }

        /**
         * 隐藏抽屉
         */
        public void hide() {
            setHideInfo();
            FT.setFromValue(1);
            FT.setToValue(0);
            PT.setInterpolator(Interpolator.LINEAR);
            PT.play();
            PT.setOnFinished((event) -> parent.getChildren().remove(this));// 移除抽屉
        }

        private void setHideInfo() {
            double translateSize = getTranslateSize();
            switch (position) {
                case TOP, BOTTOM -> {
                    clearTranslate();
                    TT.setToY(translateSize);
                }
                case RIGHT, LEFT -> {
                    clearTranslate();
                    TT.setToX(translateSize);
                }
                default -> {
                }
            }
        }

        private void setShowInfo() {
            double translateSize = getTranslateSize();
            switch (position) {
                case TOP, BOTTOM -> {
                    main.setPrefHeight(size.get());
                    main.setMaxSize(USE_COMPUTED_SIZE, USE_PREF_SIZE);
                    StackPane.setAlignment(main, Position.BOTTOM.equals(position) ? Pos.BOTTOM_CENTER : Pos.TOP_CENTER);
                    main.setTranslateY(translateSize);
                    main.setTranslateX(0);
                    clearTranslate();
                    TT.setFromY(translateSize);
                }
                case RIGHT, LEFT -> {
                    main.setPrefWidth(size.get());
                    main.setMaxSize(USE_PREF_SIZE, USE_COMPUTED_SIZE);
                    StackPane.setAlignment(main, Position.RIGHT.equals(position) ? Pos.CENTER_RIGHT : Pos.CENTER_LEFT);
                    main.setTranslateX(translateSize);
                    main.setTranslateY(0);
                    clearTranslate();
                    TT.setFromX(translateSize);
                }
                default -> {
                }
            }
        }

        /**
         * 清空移动动画属性
         */
        private void clearTranslate() {
            TT.setFromX(0);
            TT.setToX(0);
            TT.setToY(0);
            TT.setFromY(0);
        }

        /**
         * 获取移动量
         *
         * @return
         */
        private double getTranslateSize() {
            double translateSize = size.get();
            if (Position.TOP.equals(position) || Position.LEFT.equals(position)) {
                translateSize = -size.get();
            }
            return translateSize;
        }

        @Override
        public String getUserAgentStylesheet() {
            return STYLE_SHEET;
        }

    }

    /**
     * 抽屉出现的位置
     */
    public enum Position {
        TOP, RIGHT, BOTTOM, LEFT
    }

}
